﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BBInterfaceNET.ViewModels;
using Microsoft.Practices.Prism.ViewModel;
using Microsoft.Practices.Prism.Commands;
using BBInterfaceNET.Services;
using BBInterfaceNET.Events;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using System.IO;
using BBInterfaceNET.Events.Commands;
using System.ComponentModel;
using System.Xml.Linq;
using System.Diagnostics;
using ExplorerInfrastructure;
using Microsoft.Practices.Prism.Regions;

namespace BBInterfaceNET
{
    public class ShellViewModel:NotificationObject
    {
        private bool generating;

        public bool Generating
        {
            get { return generating; }
            set
            {
                if (generating != value)
                {
                    generating = value;
                    RaisePropertyChanged("Generating");
                }
            }
        }

        #region command properties
        public CommandViewModel NewProjectCommand
        {
            get
            {
                if (newProjCmd == null)
                    newProjCmd = new CommandViewModel("New Project", new DelegateCommand(OnNewProject));
                return newProjCmd;
            }
        }
        public CommandViewModel OpenProjectCommand
        {
            get
            {
                if (openProjCmd == null)
                    openProjCmd = new CommandViewModel("Open Project", new DelegateCommand(OnOpenProject));
                return openProjCmd;
            }
        }
        public CommandViewModel CloseProjectCommand
        {
            get
            {
                if (closeProjCmd == null)
                    closeProjCmd = new CommandViewModel("Close Project", new DelegateCommand(OnCloseProject, OnCanCloseProject));
                return closeProjCmd;
            }
        }

        public CommandViewModel SaveAllCommand
        {
            get
            {
                if (saveAllCmd == null)
                    saveAllCmd = new CommandViewModel("Save All", InfrastructureCommands.SaveAllCommand);
                return saveAllCmd;
            }
        }
        public CommandViewModel SaveCommand
        {
            get
            {
                if (saveCmd == null)
                    saveCmd = new CommandViewModel("Save", InfrastructureCommands.SaveCommand);
                return saveCmd;
            }
        }
        public CommandViewModel ShutdownCommand
        {
            get
            {
                if (shutdownCommand == null)
                    shutdownCommand = new CommandViewModel("Exit", new DelegateCommand(OnShutDown));
                return shutdownCommand;
            }
        }
        public CommandViewModel GenerateCommand
        {
            get
            {
                if (genCmd == null)
                    genCmd = new CommandViewModel("Generate", new DelegateCommand(OnGenerate, OnCanGenerate));
                return genCmd;
            }
        }
        #endregion
        
        public ShellViewModel(IInteractionService interactionService,
            IEventAggregator eventAggregator, IUnityContainer container)
        {
            this.interactionService = interactionService;
            this.eventAggregator = eventAggregator;
            this.container = container;
        }

        #region private methods

        #region code generation
        private bool OnCanGenerate()
        {
            IProjectExplorer explorer = null;
            try
            {
                explorer = container.Resolve<IProjectExplorer>();
            }
            catch { }
            
            return explorer!=null && explorer.IsOpened();
        }
        private void OnGenerate()
        {
            Generating = true;
            IProjectExplorer explorer = container.Resolve<IProjectExplorer>();

            if (!explorer.IsOpened()) return;

            InfrastructureCommands.SaveAllCommand.Execute(null);

            string projPath = explorer.ProjectPath;
            string outputPath = Path.Combine(projPath, "Output");

            ICodeGenerationService codeGen = container.Resolve<ICodeGenerationService>();
            codeGen.GenerateCode(projPath, explorer.ProjectName, outputPath, () => {
                container.Resolve<IDispatcherService>().Dispatch(() => {
                    Generating = false;
                });
            });
            
        }
        

        #endregion


        private void OnNewProject()
        {
            interactionService.ShowNewProjectView(arg => {
                if (arg.Result.HasValue && arg.Result.Value)
                {
                    string fname = Path.GetFileNameWithoutExtension(arg.ProjectName);
                    string pathBase = arg.ProjectPath;
                    if (arg.CreateProjectDirectory)
                        pathBase = Path.Combine(pathBase, fname);

                    string fullPath = Path.Combine(pathBase, Path.ChangeExtension(fname, ".bbpx"));

                    if (File.Exists(fullPath))
                    {
                        interactionService.ShowMessageBox("Error", "The file already exists.", res => { });
                    }
                    else
                    {
                        ProjectInfo pi = ProjectInfo.GetInstance();
                        pi.Path = fullPath;
                        pi.OsVersion = arg.SelectedOs.Name;
                        pi.FontSize = arg.SelectedDevice.DefaultFontSize;
                        pi.ScreenSize = arg.SelectedDevice.ScreenSize;

                        IProjectExplorer explorer = container.Resolve<IProjectExplorer>();
                        explorer.CreateNewProject(pi);
                        //broadcast the new project event
                        ((DelegateCommand)GenerateCommand.Command).RaiseCanExecuteChanged();
                    }
                    
                }
                
            });
        }
        
        private void OnOpenProject()
        {
            //get the path for the project
            string path = interactionService.OpenFile(true);
            if (string.IsNullOrEmpty(path)) return;
            IProjectExplorer explorer = container.Resolve<IProjectExplorer>();
            ProjectInfo pi = explorer.OpenProject(path);
            //broadcast the open project event
            OpenProjectEvent opEvent = eventAggregator.GetEvent<OpenProjectEvent>();
            opEvent.Publish(path);
            ((DelegateCommand)GenerateCommand.Command).RaiseCanExecuteChanged();
        }
        
        private void OnCloseProject()
        {
            IProjectExplorer explorer = container.Resolve<IProjectExplorer>();
            string path = Path.Combine(explorer.ProjectPath, explorer.ProjectName);
            explorer.CloseProject();
            ProjectInfo.Clear();
            //broadcast the close project event
            CloseProjectEvent cpEvent = eventAggregator.GetEvent<CloseProjectEvent>();
            cpEvent.Publish(path);
            ((DelegateCommand)GenerateCommand.Command).RaiseCanExecuteChanged();
        }

        private bool OnCanCloseProject()
        {
            IProjectExplorer explorer = container.Resolve<IProjectExplorer>();
            return explorer.IsOpened();
        }
        
        private void OnShutDown()
        {
            if (Shutdown != null)
                Shutdown(this, EventArgs.Empty);
        }
        
        #endregion


        public event EventHandler Shutdown;
        private CommandViewModel newProjCmd, openProjCmd, closeProjCmd;
        private CommandViewModel saveAllCmd, saveCmd, shutdownCommand;
        private CommandViewModel genCmd;
        private IInteractionService interactionService;
        private IEventAggregator eventAggregator;
        private IUnityContainer container;
    }
}
